/**
 * Copyright 2004 - 2007 Blue Bamboo International Inc. 
 *           All rights reserved.
 *
 *
 * Blue Bamboo PROPRIETARY/CONFIDENTIAL.
 *
 */

package com.bluebamboo.bluetools.pingpang.ui;

import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FontDialog;

import com.bluebamboo.bluetools.common.ui.utils.SWTFactory;

/**
 * DOCME
 * 
 * @author Nick.Tan
 * 
 */
public class PingPangPanel extends IoHandlerAdapter {

	private static Charset charset = Charset.forName("UTF-8");
	private static CharsetDecoder decoder = charset.newDecoder();

	private IoSession session;
	private Composite control;
	private StyledText incomingPane;
	private StyledText outcomingPane;

	public Composite createContents(Composite parent) {
		Composite container = SWTFactory.createComposite(parent, 1, GridData.FILL_BOTH);
		control = container;

		createTextArea(container);

		return container;
	}

	private void createTextArea(Composite parent) {
		Composite container = SWTFactory.createComposite(parent, parent.getFont(), 1, 1, GridData.FILL_BOTH, 0, 0);

		SashForm sashForm = new SashForm(container, SWT.VERTICAL);
		GridDataFactory.fillDefaults().grab(true, true).applyTo(sashForm);

		createIncomingArea(sashForm);
		createOutgoingArea(sashForm);

		sashForm.setWeights(new int[] {
				6,
				4
		});

	}

	private void createIncomingArea(Composite parent) {
		incomingPane = new StyledText(parent, SWT.MULTI | SWT.WRAP | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
		GridDataFactory.fillDefaults().grab(true, true).applyTo(incomingPane);
	}

	private void createOutgoingArea(final Composite parent) {
		Composite container = SWTFactory.createComposite(parent, parent.getFont(), 1, 1, GridData.FILL_BOTH, 0, 0);

		// create bar composite
		Composite barComp = SWTFactory.createComposite(container, 9, GridData.FILL_HORIZONTAL);

		Button fontButton = SWTFactory.createPushButton(barComp, "Font");

		SWTFactory.createLabel(barComp, "handler", 1);
		ComboViewer handlerViewer = new ComboViewer(barComp, SWT.READ_ONLY | SWT.BORDER);

		// create outgoing pane
		outcomingPane = new StyledText(container, SWT.MULTI | SWT.WRAP | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
		GridDataFactory.fillDefaults().grab(true, true).applyTo(outcomingPane);

		// add listeners
		fontButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				FontDialog dialog = new FontDialog(parent.getShell(), SWT.NONE);
				dialog.setText("Select Font");
				FontData defaultFont = new FontData("Courier", 10, SWT.BOLD);
				dialog.setFontList(new FontData[] {
					defaultFont
				});
				FontData newFont = dialog.open();
				if (newFont == null)
					return;
				Font font = new Font(parent.getDisplay(), newFont);
				Color color = new Color(parent.getDisplay(), dialog.getRGB());
				outcomingPane.setFont(font);
				outcomingPane.setForeground(color);
				incomingPane.setFont(font);
				incomingPane.setForeground(color);
			}
		});

		outcomingPane.addKeyListener(new KeyListener() {

			public void keyReleased(KeyEvent e) {
			}

			public void keyPressed(KeyEvent e) {
				if (e.character == '\r') {
					String message = outcomingPane.getText();
					IoBuffer buffer = IoBuffer.wrap(message.getBytes());
					session.write(buffer);
					appendOutgoingMessage(message);
					outcomingPane.setText("");
				}
			}
		});
	}

	@Override
	public void sessionCreated(IoSession session) throws Exception {
		this.session = session;
		appendSystemMessage("CONNECTED");
		updateOutcomingEnablement();
	}

	@Override
	public void sessionClosed(IoSession session) throws Exception {
		appendSystemMessage("DISCONNECTED");
		this.session = null;
		updateOutcomingEnablement();
	}

	@Override
	public void messageReceived(IoSession session, Object message) throws Exception {
		String msg = ((IoBuffer) message).getString(decoder);
		appendIncomingMessage(msg);
	}

	private void updateOutcomingEnablement() {
		control.getDisplay().asyncExec(new Runnable() {
			public void run() {
				boolean enable = session != null;
				outcomingPane.setEnabled(enable);
			}
		});
	}

	private void appendSystemMessage(String message) {
		appendMessage("<SYSTEM> " + message);
	}

	private void appendIncomingMessage(String message) {
		appendMessage("[INCOMING] " + message);
	}

	private void appendOutgoingMessage(String message) {
		appendMessage("[OUTGOING] " + message);
	}

	private void appendMessage(final String message) {
		control.getDisplay().asyncExec(new Runnable() {
			public void run() {
				incomingPane.append(message + "\n");
			}
		});
	}
}
